package com.jfast.framework.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import com.jfast.framework.log.Logger;

/**
 * 日期工具类
 * @author zengjintao
 * @version 1.0
 * @create_at 2017年5月6日 下午4:18:27
 */
public class DateUtil {
	
	private static final Logger logger = Logger.getLogger(DateUtil.class);
	
	private static final SimpleDateFormat FORMAT = getFormat("yyy-MM-dd HH:mm");
	
	private static final SimpleDateFormat YEAR = getFormat("yyyy-MMdd");
	
	private static final SimpleDateFormat SECOND = getFormat("yyy-MM-dd HH:mm:ss");
	
	private static final SimpleDateFormat DATECODE = getFormat("yyy-MM-ddHHmmss");
	
	private static final SimpleDateFormat DAY = getFormat("yyy-MM-dd");
	
	/**
	 * 获取当前时间
	 * @return
	 */
	public static Date getDate() {
		return new Date();
	}
	
	
	/**
	 * 返回指定日期格式
	 * @param format
	 * @return
	 */
	public synchronized static SimpleDateFormat getFormat(String format) {
		return new SimpleDateFormat(format);
	}
	
	/**
	 * 将日期转换成 yyy-MM-dd HH:mm 字符串形式
	 * @return
	 */
	public synchronized static String getFormatDate(Date date) {
		return FORMAT.format(date);
	}
	
	/**
	 * 将日期转换成 yyy-MM-dd HH:mm:ss 字符串形式
	 * @return
	 */
	public synchronized static String getSecondDate(Date date) {
		return SECOND.format(date);
	}
	
	/**
	 * 将日期转换成 yyy-MM-dd 字符串形式
	 * @return
	 */
	public synchronized static String getDayDate(Date date) {
		return DAY.format(date);
	}
	
	
	/**
	 * 将日期转成字符串
	 * @return
	 */
	public static String toLocaleString() {
        DateFormat formatter = DateFormat.getDateTimeInstance();
        return formatter.format(getDate());
	}
	
	public static String getYearStr(Date date) {
		return YEAR.format(date);
	}
	
	public static String getDateCode() {
		return DATECODE.format(new Date());
	}
	
	 /**
	  * 获取当天的开始时间
	  * @return
	  */
    public static Date getDayBegin() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    
    /**
     * 获取当天的结束时间
     * @return
     */
    public static Date getDayEnd() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }
    
    /**
     * 获取昨天的开始时间
     * @return
     */
    public static Date getBeginDayOfYesterday() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayBegin());
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }
    
    /**
     * 获取昨天的结束时间
     * @return
     */
    public static Date getEndDayOfYesterDay() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayEnd());
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }
    
    /*
     * 获取明天的开始时间
     */
    public static Date getBeginDayOfTomorrow() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayBegin());
        cal.add(Calendar.DAY_OF_MONTH, 1);

        return cal.getTime();
    }
    
    /*
     * 获取明天的结束时间
     */
    public static Date getEndDayOfTomorrow() {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getDayEnd());
        cal.add(Calendar.DAY_OF_MONTH, 1);
        return cal.getTime();
    }
    
    /*
     * 获取本周的开始时间
     */
    @SuppressWarnings("unused")
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getDayStartTime(cal.getTime());
    }
    /*
     * 获取本周的结束时间
     */
    public static Date getEndDayOfWeek(){
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }
    
    /*
     * 获取上周的开始时间
     */
    @SuppressWarnings("unused")
    public static Date getBeginDayOfLastWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek - 7);
        return getDayStartTime(cal.getTime());
    }
    
    /*
     * 获取上周的结束时间
     */
    public static Date getEndDayOfLastWeek(){
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfLastWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }
    
    /*
     * 获取本月的开始时间
     */
    public static Date getBeginDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        return getDayStartTime(calendar.getTime());
    }
    
    /*
     * 获取本月的结束时间
     */
    public static Date getEndDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 1, day);
        return getDayEndTime(calendar.getTime());
    }
    
    /*
     * 获取上月的开始时间
     */
    public static Date getBeginDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        return getDayStartTime(calendar.getTime());
    }
    /*
     * 获取上月的结束时间
     */
    public static Date getEndDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 2, day);
        return getDayEndTime(calendar.getTime());
    }
    
    /*
     * 获取本年的开始时间
     */
    public static Date getBeginDayOfYear() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, getNowYear());
        // cal.set
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DATE, 1);

        return getDayStartTime(cal.getTime());
    }
    
    /*
     * 获取本年的结束时间
     */
    public static Date getEndDayOfYear() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, getNowYear());
        cal.set(Calendar.MONTH, Calendar.DECEMBER);
        cal.set(Calendar.DATE, 31);
        return getDayEndTime(cal.getTime());
    }
    /*
     * 获取某个日期的开始时间
     */
    public static Timestamp getDayStartTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        if(date != null) calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }
    
    /*
     * 获取某个日期的结束时间
     */
    public static Timestamp getDayEndTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        if(date != null) calendar.setTime(date);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new Timestamp(calendar.getTimeInMillis());
    }
    
    /*
     * 获取今年是哪一年
     */
    public static Integer getNowYear() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(1));
    }
    
    /**
     * 获取本月是哪一月
     * @return
     */
    public static int getNowMonth() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return gc.get(2) + 1;
    }
    
    /**
     * 两个日期相减得到的天数
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int getDiffDays(Date beginDate, Date endDate) {
        if (beginDate == null || endDate == null) {
            throw new IllegalArgumentException("getDiffDays param is null!");
        }

        long diff = (endDate.getTime() - beginDate.getTime())
                / (1000 * 60 * 60 * 24);
        return new Long(diff).intValue();
    }
    /**
     * 两个日期相减得到的毫秒数
     * @param beginDate
     * @param endDate
     * @return
     */
    public static long dateDiff(Date beginDate, Date endDate) {
        long startTime = beginDate.getTime();
        long endTime = endDate.getTime();
        return endTime - startTime;
    }
    /**
     * 获取两个日期中的最大日期
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Date max(Date beginDate, Date endDate) {
        if (beginDate == null) {
            return endDate;
        }
        if (endDate == null) {
            return beginDate;
        }
        if (beginDate.after(endDate)) {
            return beginDate;
        }
        return endDate;
    }
    
    /**
     * 获取两个日期中的最小日期
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Date min(Date beginDate, Date endDate) {
        if (beginDate == null) {
            return endDate;
        }
        if (endDate == null) {
            return beginDate;
        }
        if (beginDate.after(endDate)) {
            return endDate;
        }
        return beginDate;
    }
   
    
    /**
     * 返回某月该季度的第一个月
     * @param date
     * @return
     */
    public static Date getFirstSeasonDate(Date date) {
        final int[] SEASON = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 };
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int sean = SEASON[cal.get(Calendar.MONTH)];
        cal.set(Calendar.MONTH, sean * 3 - 3);
        return cal.getTime();
    }
    
    /**
     * 返回某个日期下几天的日期
     * @param date
     * @param i
     * @return
     */
    public static Date getNextDay(Date date, int i) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.DATE, cal.get(Calendar.DATE) + i);
        return cal.getTime();
    }
    
    /**
     * 返回某个日期前几天的日期
     * @param date
     * @param i
     * @return
     */
    public static Date getFrontDay(Date date, int i) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.set(Calendar.DATE, cal.get(Calendar.DATE) - i);
        return cal.getTime();
    }
    
    /**
     * 获取某年某月到某年某月按天的切片日期集合（间隔天数的集合）
     * @param beginYear
     * @param beginMonth
     * @param endYear
     * @param endMonth
     * @param k
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List getTimeList(int beginYear, int beginMonth, int endYear,
                                   int endMonth, int k) {
        List list = new ArrayList();
        if (beginYear == endYear) {
            for (int j = beginMonth; j <= endMonth; j++) {
                list.add(getTimeList(beginYear, j, k));

            }
        } else {
            {
                for (int j = beginMonth; j < 12; j++) {
                    list.add(getTimeList(beginYear, j, k));
                }
                for (int i = beginYear + 1; i < endYear; i++) {
                    for (int j = 0; j < 12; j++) {
                        list.add(getTimeList(i, j, k));
                    }
                }
                for (int j = 0; j <= endMonth; j++) {
                    list.add(getTimeList(endYear, j, k));
                }
            }
        }
        return list;
    }

    /**
     * 获取指定小时之前的时间
     * @param hour
     * @return
     */
    public static  String getBeforeByHour(int hour){
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - hour);
        return getSecondDate(calendar.getTime());
    }

    /**
     * 获取指定时间天数之前的日期
     * @param dateStr (指定时间)
     * @param dayNumber (指定天数)
     * @return
     * @throws ParseException
     */
    public static  Date getDateByDayNumber(String dateStr, int dayNumber){
        Date inputDate = null;
        try {
            inputDate = SECOND.parse(dateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(inputDate);
            int inputDayOfYear = cal.get(Calendar.DAY_OF_YEAR);
            cal.set(Calendar.DAY_OF_YEAR , inputDayOfYear - dayNumber);
            return cal.getTime();
        } catch (ParseException e) {
            logger.error("获取时间异常",e);
        }
        return null;
    }

    //获取某年某月按天切片日期集合（某个月间隔多少天的日期集合）
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static List getTimeList(int beginYear, int beginMonth, int k) {
        List list = new ArrayList();
        Calendar begincal = new GregorianCalendar(beginYear, beginMonth, 1);
        int max = begincal.getActualMaximum(Calendar.DATE);
        for (int i = 1; i < max; i = i + k) {
            list.add(begincal.getTime());
            begincal.add(Calendar.DATE, k);
        }
        begincal = new GregorianCalendar(beginYear, beginMonth, max);
        list.add(begincal.getTime());
        return list;
    }

    @SuppressWarnings("rawtypes")
	public static List getPart(String orderBy, int day){
        if(orderBy.equals("hour")){
            return getSectionByOneHour(new Date());
        }else if(orderBy.equals("day")){
            return  getSectionByOneDay(day);
        }
        return null;
    }


    /**
     * 获取当天凌晨据当前时间每一个小时的时间段
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unused", "unchecked" })
	public static List<String> getSectionByOneHour(Date endDate){
        Date startDate = getDayBegin();
        int times = (int) dateDiff(startDate,endDate);
        int hourCount = times/1000/60/60;
        //开始时间为0秒，第一次循环为900秒
        int aecondValueZero = 0;
        //开始时间为-900秒，第一次循环为0秒
        int aecondValueNineHundred = -3600;

        //循环时间为00：00 ~ endDate
        List<String> list = new ArrayList();
        for (int i = 0; i <= hourCount; i++) {
            //每次循环之前加1小时
            aecondValueZero = aecondValueZero + 3600;
            //每次循环之前加1小时
            aecondValueNineHundred = aecondValueNineHundred + 3600;
            //初始时间都为00：00
            String atimeInitialFront = "00:00";
            String ATimeInitialAfter = "00:00";
            //判断初始秒树是否为0
            if (aecondValueZero != 0) {
                //换算成小时
                int AHourst = (Integer.valueOf(aecondValueZero) / 3600);
                //换算成分钟
                int Aminute = (Integer.valueOf(aecondValueZero) % 3600 / 60);
                //把生成的时间转化成字符串
                String hourst = String.valueOf(AHourst);
                String minute = String.valueOf(Aminute);
                //如果小时的长度等于1个，在其前面加个0
                if (hourst.length() == 1) {
                    hourst = "0" + hourst;
                }
                //如果小时的到达24点让其初始化为00
                if (hourst.equals("24")) {
                    hourst = "00";
                }
                //如果分钟的长度等于1个，在其前面加个0
                if (minute.length() == 1) {
                    minute = "0" + minute;
                }
                //拼接小时和分钟
                ATimeInitialAfter = hourst + ":" + minute; // + ":" + Asecond;
            }
            //循环时间为00：30~00：00
            if (aecondValueNineHundred != 0) {
                //换算成小时
                int AHourst = (Integer.valueOf(aecondValueNineHundred) / 3600);
                //换算成分钟
                int Aminute = (Integer.valueOf(aecondValueNineHundred) % 3600 / 60);
                //把生成的时间转化成字符串
                String hourst = String.valueOf(AHourst);
                String minute = String.valueOf(Aminute);
                //如果小时的长度等于1个，在其前面加个0
                if (hourst.length() == 1) {
                    hourst = "0" + hourst;
                }
                //如果小时的到达24点让其初始化为00
                if (hourst.equals("24")) {
                    hourst = "00";
                }
                //如果分钟的长度等于1个，在其前面加个0
                if (minute.length() == 1) {
                    minute = "0" + minute;
                }
                //拼接小时和分钟
                atimeInitialFront = hourst + ":" + minute; // + ":" + Asecond;
            }
            //将时间和所有字段放入map中初始为0
            list.add(atimeInitialFront);
        }
        return list;
    }

    /**
     * 按每天分成时间段
     * @return
     */
	public static List<String> getSectionByOneDay(int day){
        String nowTime = getSecondDate(new Date());//当前时间开始前
        Date startDate = getDateByDayNumber(nowTime,day);
        String startTime = getSecondDate(startDate);
        String afterDay = null;
        List<String> list = new ArrayList<String>();
        for (int i=0;i<day;i++){
            afterDay = getDayAfter(startTime);
            list.add(afterDay);
            startTime = afterDay;
        }
        return list;
    }

    /**
     * 获取某个时间后一天日期
     * @param dateStr
     * @return
     */
    public static String getDayAfter(String dateStr){
        Calendar calendar = Calendar.getInstance();
        try {
            Date date = DAY.parse(dateStr);
            calendar.setTime(date);
            int day = calendar.get(Calendar.DATE);
            calendar.set(Calendar.DATE,day + 1);
            return  DAY.format(calendar.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

}
